﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Analytics;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public AudioClip[] audios;
    public enum SweetsType
    {
        EMPTY,
        NORMAL,
        BARRIER,
        ROW_CLEAR,
        COLUMN_CLEAR,
        RAINBOWCANDY,
        COUNT
    }

    private Dictionary<SweetsType, GameObject> sweetPrefabDict;

    [System.Serializable]
    public struct SweetPrefab
    {
        public SweetsType type;
        public GameObject prefab;
    }

    public SweetPrefab[] SweetPrefabs;
    private gameSweet[,] sweets;
    private string NowGamer;
    public int xColumn;
    public int yRow;
    public float filltime;
    public GameObject gridPrefab;
    //About UI
    public Text timeText;
    public float gameTime = 3;
    private bool gameOver;
    public int playerScore;
    public Text playerScoreText;
    private float addScoreTime=0;
    private float currentScore;
    public Text finalScoreText;
    private GameID theGameId;

    //单例
    private static GameManager _instance;
    public static GameManager Instance
    {
        get
        {
            return _instance;
        }

        set
        {
            _instance = value;
        }
    }

    private gameSweet pressedSweet, enteredSweet;
    public GameObject GameOverPanel;

    private void Awake()
    {
        _instance = this;
        theGameId = GameObject.Find("Main Camera").GetComponent<GameID>();
        NowGamer = theGameId.nowGamer;
        Debug.Log(NowGamer);
    }
    public Vector2 CorrectPosition(int x, int y)
    {
        return new Vector2(x-xColumn/2f+transform.position.x,y-yRow/2+transform.position.y);
    }

    public gameSweet CreatNewSweet(int x, int y, SweetsType type)
    {
        GameObject newSweet =Instantiate(sweetPrefabDict[type], CorrectPosition(x, y), Quaternion.identity);
        newSweet.transform.parent = transform;
        sweets[x, y] = newSweet.GetComponent<gameSweet>();
        sweets[x,y].Init(x,y,this,type);
        return sweets[x, y];
    }

    void Start()
    {
        GameObject.Find("Canvas").GetComponent<AudioSource>().clip = audios[getMusic()];
        GameObject.Find("Canvas").GetComponent<AudioSource>().Play();
        //字典的实例化
        sweetPrefabDict = new Dictionary<SweetsType, GameObject>();
        for (int i = 0; i < SweetPrefabs.Length; i++)
        {
            if (!sweetPrefabDict.ContainsKey(SweetPrefabs[i].type))
            {
                sweetPrefabDict.Add(SweetPrefabs[i].type, SweetPrefabs[i].prefab);
            }
        }
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                GameObject chocolate = Instantiate(gridPrefab, CorrectPosition(x, y), Quaternion.identity);
                chocolate.transform.SetParent(transform);
            }
        }
        sweets = new gameSweet[xColumn, yRow];
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                CreatNewSweet(x, y, SweetsType.EMPTY);
            }
        }
        MakeBarrier(Random.Range(0,xColumn),Random.Range(0,yRow));
        MakeBarrier(3,3);
        MakeBarrier(3,6);
        MakeBarrier(6,3);
        MakeBarrier(6,6);
        StartCoroutine(AllFill());
    }

    void Update()
    {
        if (gameTime <= 0)
        {
            gameTime = 0;
            //显示失败面板，播放失败动画
            gameOver = true;
            GameOverPanel.SetActive(true);
            finalScoreText.text = playerScore.ToString();
        }
        gameTime -= Time.deltaTime;
        timeText.text = gameTime.ToString("0");//0的意思是取整，0.0意思是一位小数
        if (addScoreTime <= 0.05f)
        {
            addScoreTime += Time.deltaTime;
        }
        else
        {
            if(currentScore<playerScore)
            {
                currentScore++;
                playerScoreText.text = currentScore.ToString();
                addScoreTime = 0;
            }
        }
    }

    public IEnumerator AllFill()
    {
        bool needRefill = true;
        while (needRefill)
        {
            yield return new WaitForSeconds(filltime);
            while (Fill())
            {
                yield return new WaitForSeconds(filltime);
            }

            needRefill=ClearAllMatchedSweet();
        }

    }

    //产生障碍
    private void MakeBarrier(int x,int y)
    {
        Destroy(sweets[x,y].gameObject);
        CreatNewSweet(x, y, SweetsType.BARRIER);
    }

    public bool Fill()
    {
        bool fillNotFinished = false;
        for (int y = 1; y < yRow; y++)
        {
            for (int x = 0; x < xColumn; x++)
            {
                gameSweet sweet = sweets[x,y];
                if (sweet.canMoved())
                {
                    gameSweet sweetBelow = sweets[x,y-1];
                    if (sweetBelow.Type == SweetsType.EMPTY)
                    {
                        Destroy(sweetBelow.gameObject);
                        sweet.MovedComponent.Move(x,y-1,filltime);
                        sweets[x,y-1] = sweet;
                        CreatNewSweet(x, y, SweetsType.EMPTY);
                        fillNotFinished = true;
                    }
                    else
                    {
                        for (int down = -1; down <= 1; down++)
                        {
                            if (down != 0)
                            {
                                int downX = x + down;
                                if (downX >= 0 && downX < xColumn)
                                {
                                    gameSweet dawnSweet = sweets[downX, y - 1];
                                    if (dawnSweet.Type == SweetsType.EMPTY)
                                    {
                                        bool canfill = true;
                                        for (int aboveY = y; aboveY < yRow; aboveY++)
                                        {
                                            gameSweet sweetAbove = sweets[downX, aboveY];
                                            if (sweetAbove.canMoved())
                                            {
                                                break;
                                            }
                                            else if (!sweetAbove.canMoved() && sweetAbove.Type != SweetsType.EMPTY)
                                            {
                                                canfill = false;
                                                break;
                                            }

                                        }

                                        if (!canfill)
                                        {
                                            Destroy(dawnSweet.gameObject);
                                            sweet.MovedComponent.Move(downX,y-1,filltime);
                                            sweets[downX, y - 1] = sweet;
                                            CreatNewSweet(x, y, SweetsType.EMPTY);
                                            fillNotFinished = true;
                                            break;
                                        }
                                    }
                                }
                            }
                            
                        }
                    }
                }
            }
        }

        for (int x = 0; x < xColumn; x++)
        {
            gameSweet sweet = sweets[x, yRow - 1];
            if (sweet.Type == SweetsType.EMPTY)
            {
                //GameObject newSweet = Instantiate(sweetPrefabDict[type], CorrectPosition(x, y), Quaternion.identity);
                //newSweet.transform.parent = transform;
                //sweets[x, y] = newSweet.GetComponent<gameSweet>();
                //sweets[x, y].Init(x, y, this, type);
                //return sweets[x, y];
                Destroy(sweet.gameObject);
                GameObject newSweet = Instantiate(sweetPrefabDict[SweetsType.NORMAL], CorrectPosition(x, yRow),
                    Quaternion.identity);
                newSweet.transform.parent = transform;
                sweets[x, yRow - 1] = newSweet.GetComponent<gameSweet>();
                sweets[x, yRow - 1].Init(x, yRow - 1, this, SweetsType.NORMAL);
                sweets[x, yRow - 1].MovedComponent.Move(x, yRow - 1,filltime);
                sweets[x, yRow - 1].ColoredComponent.SetColor((ColorSweet.ColorType)Random.Range(0, sweets[x, yRow - 1].ColoredComponent.NumColors));
                fillNotFinished = true;
            }

        }

        return fillNotFinished;
    }

    public bool isFriend(gameSweet sweet1, gameSweet sweet2)
    {
        return (sweet1.X == sweet2.X && Mathf.Abs(sweet1.Y - sweet2.Y) == 1) ||
               (sweet1.Y == sweet2.Y && Mathf.Abs(sweet1.X - sweet2.X) == 1);
    }

    private void ExchangeSweets(gameSweet sweet1, gameSweet sweet2)
    {
        if (sweet1.canMoved() && sweet2.canMoved())
        {
            sweets[sweet1.X, sweet1.Y] = sweet2;
            sweets[sweet2.X, sweet2.Y] = sweet1;
            if (MatchSweets(sweet1, sweet2.X, sweet2.Y) != null || MatchSweets(sweet2, sweet1.X, sweet1.Y) != null||sweet1.Type==SweetsType.RAINBOWCANDY
                ||sweet2.Type==SweetsType.RAINBOWCANDY)
            {
                int tempX = sweet1.X, tempY = sweet1.Y;
                sweet1.MovedComponent.Move(sweet2.X, sweet2.Y, filltime);
                sweet2.MovedComponent.Move(tempX, tempY, filltime);
                if (sweet1.Type == SweetsType.RAINBOWCANDY && sweet1.canColored() && sweet2.canColored())
                {
                    ClearColorSweet clearcolor = sweet1.GetComponent<ClearColorSweet>();
                    if (clearcolor != null)
                    {
                        clearcolor.ClearColor = sweet2.ColoredComponent.Color;
                    }
                    ClearSweet(sweet1.X, sweet1.Y);

                }
                if (sweet2.Type == SweetsType.RAINBOWCANDY && sweet1.canColored() && sweet2.canColored())
                {
                    ClearColorSweet clearcolor = sweet2.GetComponent<ClearColorSweet>();
                    if (clearcolor != null)
                    {
                        clearcolor.ClearColor = sweet1.ColoredComponent.Color;
                    }
                    ClearSweet(sweet2.X, sweet2.Y);
                }
                ClearAllMatchedSweet();
                StartCoroutine(AllFill());
                pressedSweet = null;
                enteredSweet = null;
            }
            else
            {
                sweets[sweet1.X, sweet1.Y] = sweet1;
                sweets[sweet2.X, sweet2.Y] = sweet2;
            }
        }
    }

    public void PressSweet(gameSweet sweet)
    {
        if (gameOver) return;
        pressedSweet = sweet;
    }

    public void EnterSweet(gameSweet sweet)
    {
        if (gameOver) return;
        enteredSweet = sweet;
    }

    public void ReleaseSweet()
    {
        if (gameOver) return;
        if (isFriend(pressedSweet, enteredSweet))
        {
            ExchangeSweets(pressedSweet,enteredSweet);
        }
    }

    public List<gameSweet> MatchSweets(gameSweet sweet,int newX,int newY)
    {
        if (sweet.canColored())
        {
            ColorSweet.ColorType color = sweet.ColoredComponent.Color;
            List<gameSweet> matchRowSweets=new List<gameSweet>();
            List<gameSweet> matchLineSweets=new List<gameSweet>();
            List<gameSweet> finishedMatchSweets=new List<gameSweet>();

            matchRowSweets.Add(sweet);
            for (int i = 0; i < 2; i++)
            {
                for (int xDistance = 1; xDistance < xColumn; xDistance++)
                {
                    int x;
                    if (i == 0)
                    {
                        x = newX - xDistance;
                    }
                    else
                    {
                        x = newX + xDistance;
                    }

                    if (x < 0 || x >= xColumn)
                    {
                        break;
                    }

                    if (sweets[x, newY].canColored() && sweets[x, newY].ColoredComponent.Color == color)
                    {
                        matchRowSweets.Add(sweets[x, newY]);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    finishedMatchSweets.Add(matchRowSweets[i]);
                }
            }

            if (matchRowSweets.Count >= 3)
            {
                for (int i = 0; i < matchRowSweets.Count; i++)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        for (int yDistance = 1; yDistance < yRow; yDistance++)
                        {
                            int y;
                            if (j == 0)
                            {
                                y = newY - yDistance;
                            }
                            else
                            {
                                y = newY + yDistance;
                            }

                            if (y < 0 || y >= yRow)
                            {
                                break;
                            }

                            if (sweets[matchRowSweets[i].X, y].canColored() &&
                                sweets[matchRowSweets[i].X, y].ColoredComponent.Color == color)
                            {
                                matchLineSweets.Add(sweets[matchRowSweets[i].X, y]);
                            }
                            else break;

                        }
                    }
                    if (matchLineSweets.Count < 2)
                    {
                        matchLineSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchLineSweets.Count; j++)
                        {
                            finishedMatchSweets.Add(matchLineSweets[j]);
                        }
                        matchLineSweets.Clear();
                    }

                }

            }

            if (finishedMatchSweets.Count >= 3)
            {
                return finishedMatchSweets;
            }
            matchRowSweets.Clear();
            matchLineSweets.Clear();

            matchLineSweets.Add(sweet);
            for (int i = 0; i < 2; i++)
            {
                for (int yDistance = 1; yDistance < yRow; yDistance++)
                {
                    int y;
                    if (i == 0)
                    {
                        y = newY- yDistance;
                    }
                    else
                    {
                        y = newY + yDistance;
                    }

                    if (y < 0 || y >= yRow)
                    {
                        break;
                    }

                    if (sweets[newX,y].canColored() && sweets[newX,y].ColoredComponent.Color == color)
                    {
                        matchLineSweets.Add(sweets[newX,y]);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            
            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        for (int xDistance = 1; xDistance < xColumn; xDistance++)
                        {
                            int x;
                            if (j == 0)
                            {
                                x = newX - xDistance;
                            }
                            else
                            {
                                x = newX + xDistance;
                            }

                            if (x < 0 || x >= xColumn)
                            {
                                break;
                            }

                            if (sweets[x, matchLineSweets[i].Y].canColored() &&
                                sweets[x, matchLineSweets[i].Y].ColoredComponent.Color == color)
                            {
                                matchRowSweets.Add(sweets[x, matchLineSweets[i].Y]);
                            }
                            else break;

                        }
                    }
                    if (matchRowSweets.Count < 2)
                    {
                        matchRowSweets.Clear();
                    }
                    else
                    {
                        for (int j = 0; j < matchRowSweets.Count; j++)
                        {
                            finishedMatchSweets.Add(matchRowSweets[j]);
                        }
                        matchRowSweets.Clear();
                    }
                }

            }
            
            if (matchLineSweets.Count >= 3)
            {
                for (int i = 0; i < matchLineSweets.Count; i++)
                {
                    finishedMatchSweets.Add(matchLineSweets[i]);
                }
            }

            if (finishedMatchSweets.Count >= 3)
            {
                return finishedMatchSweets;
            }
        }
        return null;
    }

    public bool ClearSweet(int x, int y)
    {
        if (sweets[x, y].canClear()&&!sweets[x,y].ClearedComponent.IsClearing)
        {
            sweets[x, y].ClearedComponent.Clear();
            CreatNewSweet(x, y, SweetsType.EMPTY);
            ClearBarrier(x,y);
            gameTime += 0.1F;
            return true;
        }

        return false;
    }

    private void ClearBarrier(int x,int y)
    {
        for (int friendx = x-1; friendx <= x+1; friendx++)
        {
            if (friendx != x && friendx >= 0 && friendx < xColumn)
            {
                if (sweets[friendx, y].Type == SweetsType.BARRIER && sweets[friendx, y].canClear())
                {
                    sweets[friendx,y].ClearedComponent.Clear();
                    CreatNewSweet(friendx, y, SweetsType.EMPTY);
                }
            }
        }
        for (int friendy = y - 1; friendy <= y + 1; friendy++)
        {
            if (friendy != y && friendy >= 0 && friendy < yRow)
            {
                if (sweets[x, friendy].Type == SweetsType.BARRIER && sweets[x, friendy].canClear())
                {
                    sweets[x, friendy].ClearedComponent.Clear();
                    CreatNewSweet(x, friendy, SweetsType.EMPTY);
                }
            }
        }
    }

    private bool ClearAllMatchedSweet()
    {
        bool needRefill = false;
        for (int y = 0; y < yRow; y++)
        {
            for (int x = 0; x < xColumn; x++)
            {
                if (sweets[x, y].canClear())
                {
                    List<gameSweet> matchList = MatchSweets(sweets[x, y], x, y);
                    if (matchList != null)
                    {
                        SweetsType specialSweetsType = SweetsType.COUNT;
                        gameSweet randomSweet = matchList[Random.Range(0, matchList.Count)];
                        int specialSweetX = randomSweet.X;
                        int specialSweetY = randomSweet.Y;
                        if (matchList.Count == 4)
                        {
                            specialSweetsType = (SweetsType)Random.Range((int) SweetsType.ROW_CLEAR, (int) SweetsType.COLUMN_CLEAR+1);
                        }
                        //五个就产生彩虹糖
                        else if (matchList.Count >= 5)
                        {
                            specialSweetsType = SweetsType.RAINBOWCANDY;
                        }
                        for (int i = 0; i < matchList.Count; i++)
                        {
                            if (ClearSweet(matchList[i].X, matchList[i].Y))
                            {
                                needRefill = true;
                            }
                        }

                        if (specialSweetsType != SweetsType.COUNT)
                        {
                            Destroy(sweets[specialSweetX,specialSweetY]);
                            gameSweet newSweet = CreatNewSweet(specialSweetX, specialSweetY, specialSweetsType);
                            if (specialSweetsType==SweetsType.ROW_CLEAR||specialSweetsType==SweetsType.COLUMN_CLEAR&&newSweet.canColored()&&matchList[0].canColored())
                            {
                                newSweet.ColoredComponent.SetColor(matchList[0].ColoredComponent.Color);
                            }
                            else if (specialSweetsType == SweetsType.RAINBOWCANDY)
                            {
                                newSweet.ColoredComponent.SetColor(ColorSweet.ColorType.ANY);
                            }
                            //彩虹糖的产生
                        }
                    }

                }
            }
        }

        return needRefill;
    }

    public void ReturnToMain()
    {
        setMoney(playerScore + getMoney());
        InsertScore(playerScore);
        SceneManager.LoadScene(1);
    }

    public void Replay()
    {
        setMoney(playerScore + getMoney());
        InsertScore(playerScore);
        SceneManager.LoadScene(2);
    }
    //清除行的方法
    public void ClearRow(int row)
    {
        for (int i = 0; i < xColumn; i++)
        {
            ClearSweet(i, row);
        }
    }
    //清除列的方法
    public void ClearColumn(int column)
    {
        for (int y = 0; y < yRow; y++)
        {
            ClearSweet(column, y);
        }
    }
    //清除颜色的方法
    public void ClearColor(ColorSweet.ColorType color)
    {
        for (int x = 0; x < xColumn; x++)
        {
            for (int y = 0; y < yRow; y++)
            {
                if (sweets[x, y].canColored() && (sweets[x, y].ColoredComponent.Color == color ||
                    color == ColorSweet.ColorType.ANY))
                {
                    ClearSweet(x, y);
                }
            }
        }
    }

    private void InsertScore(int score)
    {
        if(score> PlayerPrefs.GetInt("@MaxScore9"))
        {
            int i;
            for ( i = 8; i >= 0; i--)
            {
                if (score > PlayerPrefs.GetInt("@MaxScore" + i.ToString()))
                {
                    PlayerPrefs.SetInt("@MaxScore" + (i + 1).ToString(),PlayerPrefs.GetInt("@MaxScore" + i.ToString()));
                    PlayerPrefs.SetString("@MaxName"+(i+1).ToString(),PlayerPrefs.GetString("@MaxName"+i.ToString()));
                }
                else
                {
                    PlayerPrefs.SetInt("@MaxScore" + (i + 1).ToString(), score);
                    PlayerPrefs.SetString("@MaxName" + (i + 1).ToString(), theGameId.nowGamer);
                    break;
                }
            }

            if (i == -1)
            {
                PlayerPrefs.SetInt("@MaxScore0",score);
                PlayerPrefs.SetString("@MaxName0",theGameId.nowGamer);
            }
        }
        else return;
    }

    public int getMusic()
    {
        return PlayerPrefs.GetInt(NowGamer + "Music");
    }

    public float getMoney()
    {
        return PlayerPrefs.GetFloat(NowGamer + "Money");
    }

    public void setMoney(float money)
    {
        Debug.Log(money);
        PlayerPrefs.SetFloat(NowGamer + "Money", money);
    }
}
